package com.nuanshui.heatedloan.controller;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.nuanshui.heatedloan.baseservice.model.UserAgent;
import com.nuanshui.heatedloan.baseservice.facade.CommonConfigService;
import com.nuanshui.heatedloan.dubbo.DubboResponse;
import com.nuanshui.framework.exception.BizException;
import com.nuanshui.framework.exception.GlobalErrorCode;
import com.nuanshui.framework.lang.SysStringUtils;
import com.nuanshui.framework.utils.LogUtil;
import com.nuanshui.framework.utils.redis.JedisUtil;
import com.nuanshui.heatedloan.constant.CommonConfigKey;
import com.nuanshui.heatedloan.constant.GlobalParam;
import com.nuanshui.heatedloan.dubbo.extension.DubboContextManager;
import com.nuanshui.heatedloan.extension.validator.ParamValidator;
import com.nuanshui.heatedloan.middleware.fastjson.FastjsonIgnoreFilter;
import com.nuanshui.heatedloan.userinfo.model.SimpleUserInfo;
import com.nuanshui.heatedloan.userinfo.model.User;
import com.nuanshui.heatedloan.userinfo.tool.UserTool;
import com.nuanshui.heatedloan.userinfo.vo.IncrUserIntegralVo;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.ServletRequestDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.util.List;

/**
 * rest-api工程的基类Controller
 *
 * @author odin
 */
public class BaseController {
    protected Logger log = LoggerFactory.getLogger(getClass());
    protected Logger bizErrorLog = LoggerFactory.getLogger("biz_log");
    private final static ThreadLocal<HttpServletRequest> request = new ThreadLocal<HttpServletRequest>();
    private final static ThreadLocal<HttpServletResponse> response = new ThreadLocal<HttpServletResponse>();
    protected final Integer DEFAULT_PAGE_SIZE = 20;

    @Autowired
    protected JedisUtil jedisUtil;

    private CommonConfigService commonConfigService;

    protected CommonConfigService getCommonConfigService() {
        if (commonConfigService == null) {
            commonConfigService = DubboContextManager.getDubboBean(CommonConfigService.class,GlobalParam.BASESERVICE_DUBBO_SERVER_VERSION);
        }
        return commonConfigService;
    }

    @SuppressWarnings("static-access")
    @ModelAttribute
    public void init(final HttpServletRequest request,
                     final HttpServletResponse response) {
        this.response.set(response);
        this.request.set(request);
    }

    protected HttpServletRequest getRequest() {
        return request.get();
    }

    protected HttpServletResponse getResponse() {
        return response.get();
    }

    @InitBinder
    protected void initBinder(final HttpServletRequest request,
                              final ServletRequestDataBinder binder) throws Exception {
        binder.addValidators(new ParamValidator());
    }

    /**
     * 获取当前用户
     *
     * @param
     * @author guohao
     * @date 2015年6月8日 下午6:14:58
     */
    public User getCurrentUser() {
        User user = getCurrentUserNotCheckEmptyId();
        if (user == null || StringUtils.isEmpty(user.getId())) {
            throw new BizException(GlobalErrorCode.UNAUTHORIZED, "need login first.");
        }

        return user;
    }

    public User getCurrentUserNotCheckEmptyId() {

        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null) {
            Object principal = auth.getPrincipal();
            if (principal instanceof User) {
                User user = (User) principal;
                if (user != null && !user.isAnonymous()) {
                    return user;
                }
            }

            if (auth.getClass().getSimpleName().indexOf("Anonymous") < 0) {
                log.error("Unknown authentication encountered, ignore it. " + auth);
            }
        }

        User empty = new User();
        empty.setId("");
        return empty;
    }

    /**
     * 成功
     *
     * @param
     * @author guohao
     * @date 2015年6月9日 上午10:30:57
     */
    @SuppressWarnings({"rawtypes", "unchecked"})
    public String success(Object obj) {
        String uri = getRequest().getRequestURI();
        ResponseObject result = new ResponseObject();
        result.setSubErrorCode(0);
        result.setData(obj);
        if (!uri.endsWith("loadConfig") && !jedisUtil.exists("common_key_" + CommonConfigKey.SERVER_ADDRESS_LIST)) {
            List<String> list = getCommonConfigService().listValueByKey(CommonConfigKey.SERVER_ADDRESS_LIST);
            result.setServerIps(list);
            jedisUtil.set("common_key_" + CommonConfigKey.SERVER_ADDRESS_LIST, JSON.toJSONString(list));
        }

        result.setData(obj);
        String str = JSON.toJSONString(result, new FastjsonIgnoreFilter("callbacks", "limit", "offset", "pageNumber", "pageSize", "searchCount"), SerializerFeature.DisableCircularReferenceDetect);
        String callback = getRequest().getParameter("callback");
        if (!SysStringUtils.isEmpty(callback)) {
            str = callback + "(" + str + ")";
            return str;
        }
        return str;
    }

    @SuppressWarnings("rawtypes")
    public String fail(Integer errorCode) {
        ResponseObject result = new ResponseObject();
        result.setSubErrorCode(errorCode);
        String str = JSON.toJSONString(result);
        String callback = getRequest().getParameter("callback");
        if (!SysStringUtils.isEmpty(callback)) {
            str = callback + "(" + str + ")";
            return str;
        }
        return str;
    }

    public String chinaToUnicode(String str) {
        String result = "";
        for (int i = 0; i < str.length(); i++) {
            int chr1 = str.charAt(i);
            if (chr1 >= 19968 && chr1 <= 171941) {//汉字范围 \u4e00-\u9fa5 (中文)
                result += "\\u" + Integer.toHexString(chr1);
            } else {
                result += str.charAt(i);
            }
        }
        return result;
    }

    @SuppressWarnings({"rawtypes", "unchecked"})
    public String success(Object obj, String score) {
        ResponseObject result = new ResponseObject();
        result.setScore(score);
        result.setData(obj);
        return JSON.toJSONString(result, new FastjsonIgnoreFilter("callbacks"));
    }

    public String convertToJsonp(String str) {
        String callback = getRequest().getParameter("callback");
        if (!SysStringUtils.isEmpty(callback)) {
            str = callback + "(" + str + ")";
            return str;
        }
        return str;
    }


    public String success(Object data, IncrUserIntegralVo incrUserIntegralVo) {
        DefaultResponseObject result = new DefaultResponseObject();
        result.setData(data);
        if (incrUserIntegralVo.isShowAlertMsg()) {
            result.setScore(incrUserIntegralVo.getAlertMsg());
        }
        if (incrUserIntegralVo.isUpgrade()) {
            result.setLevel(incrUserIntegralVo.getLevel());
        }
        result.setAcquireScore(incrUserIntegralVo.getAcquireScore());
        result.setNextScore(incrUserIntegralVo.getNextScore());
        return JSON.toJSONString(result, new FastjsonIgnoreFilter("callbacks"), SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNonStringKeyAsString);
    }

    public String successWithoutNull(Object data, IncrUserIntegralVo incrUserIntegralVo) {
        DefaultResponseObject result = new DefaultResponseObject();
        result.setData(data);
        if (incrUserIntegralVo.isShowAlertMsg()) {
            result.setScore(incrUserIntegralVo.getAlertMsg());
        }
        if (incrUserIntegralVo.isUpgrade()) {
            result.setLevel(incrUserIntegralVo.getLevel());
        }
        result.setAcquireScore(incrUserIntegralVo.getAcquireScore());
        result.setNextScore(incrUserIntegralVo.getNextScore());
        return JSON.toJSONString(result, new FastjsonIgnoreFilter("callbacks"));
    }

    public String success(IncrUserIntegralVo incrUserIntegralVo) {
        DefaultResponseObject result = new DefaultResponseObject();
        if (incrUserIntegralVo.isShowAlertMsg()) {
            result.setScore(incrUserIntegralVo.getAlertMsg());
        }
        if (incrUserIntegralVo.isUpgrade()) {
            result.setLevel(incrUserIntegralVo.getLevel());
        }
        result.setAcquireScore(incrUserIntegralVo.getAcquireScore());
        result.setNextScore(incrUserIntegralVo.getNextScore());
        return JSON.toJSONString(result, new FastjsonIgnoreFilter("callbacks"), SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNonStringKeyAsString);
    }

    public String success() {
        DefaultResponseObject result = new DefaultResponseObject();
        return JSON.toJSONString(result, new FastjsonIgnoreFilter("callbacks"), SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNonStringKeyAsString);

    }

    @SuppressWarnings({"unchecked", "rawtypes"})
    public String success(DubboResponse response) {

        ResponseObject result = new ResponseObject();
        if (response.isSuccess()) {
            result.setStatus(GlobalErrorCode.SUCESS);
            result.setData(response.getData());
        } else {
            result.setStatus(response.getCode() == 0 ? GlobalErrorCode.UNKNOWN : GlobalErrorCode.valueOf(response.getCode()));
            result.setMoreInfo(response.getMsg());

        }
        return JSON.toJSONString(result, new FastjsonIgnoreFilter("callbacks"), SerializerFeature.WriteMapNullValue, SerializerFeature.WriteNonStringKeyAsString);

    }

    @SuppressWarnings("rawtypes")
    public String fail() {
        ResponseObject result = new ResponseObject();
        return JSON.toJSONString(result);
    }

    /**
     * 参数不正确
     *
     * @param
     * @author guohao
     * @date 2015年6月9日 上午10:29:50
     */
    @SuppressWarnings({"rawtypes"})
    public String argumentError(String msg) {
        ResponseObject result = new ResponseObject(GlobalErrorCode.INVALID_ARGUMENT);
        result.setMoreInfo(msg);
        return JSON.toJSONString(result);
    }

    /**
     * 逻辑错误
     *
     * @param
     * @author guohao
     * @date 2015年6月9日 上午10:31:02
     */
    public String error(String msg) {
        LogUtil.info(bizErrorLog, msg);
        throw new BizException(GlobalErrorCode.UNKNOWN, msg);
    }


    protected UserAgent getUserAgent() {
        return (UserAgent) getRequest().getAttribute(GlobalParam.USER_AGENT);
    }


    public String getSafeToken() {
        UserAgent userAgent = (UserAgent) getRequest().getAttribute(GlobalParam.USER_AGENT);
        String safeToken = userAgent.getSafeToken();
        return safeToken;
    }

    /**
     * 判断是否是微信用户
     *
     * @author Junyan2015
     * @date 2016年4月19日 上午9:11:30
     */
    protected boolean isFromWechat() {
        String channel = getUserAgent().getChannel();
        if (channel == null) return false;
        if ("weixin".equals(channel)) return true;

        return false;
    }

    protected boolean isJsonpRequest() {
        String callback = getRequest().getParameter("callback");
        return StringUtils.isNotEmpty(callback);
    }

    /**
     * 获取微信用户的openId
     *
     * @author Junyan2015
     * @date 2016年4月19日 上午9:13:06
     */
    protected String getWechatOpenId() {

        if (isFromWechat()) {
            String openid = getRequest().getHeader("openid");
            if (openid == null) log.error("openid为空！");
            return openid;
        } else {
            log.error("该用户访问不来自微信，因此不能获取openid");
        }
        return null;
    }


}
